package com.gateio.flutter.lib_core

import android.util.Log
import androidx.annotation.Keep
import androidx.annotation.NonNull
import com.gateio.flutter.lib_core.logger.GTLoggerHostApi
import com.gateio.flutter.lib_core.logger.GTLoggerHostApiImpl
import com.gateio.flutter.lib_core.model.GTFlutterEventModel
import com.google.gson.Gson

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import java.util.concurrent.CopyOnWriteArrayList

/** LibCorePlugin */
@Keep
class GTLibCoreFlutterPlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler {

  companion object {
    // 全局统一 gson
    val gson = Gson()

    // 多引擎 MessageChannel 存储
    internal var messageChannelList: MutableList<GTMessageChannelFlutterApi> = mutableListOf()
    // 多引擎 methodChannel 存储
    private var methodChannelList: MutableList<MethodChannel?> = mutableListOf()
    // 多引擎 EventChannel 存储
    private var eventSinkList: MutableList<EventChannel.EventSink?> = mutableListOf()
    // 保存粘性消息
    private var globalStickyMessageList: CopyOnWriteArrayList<String> = CopyOnWriteArrayList()

    @JvmStatic
    fun <E : Enum<E>> sendMessage(eventModel: GTFlutterEventModel<E>, sticky: Boolean = false) {
      // 数据统一转为JSON
      val messageJson = eventModel.toJSON()

      // 如果是粘性事件，在没有通道时保存起来，下次 onListen 后再转发
      if (eventSinkList.isEmpty() && sticky) {
        globalStickyMessageList.add(messageJson)
      } else {
        // 向 Flutter 发送消息
        eventSinkList.forEach { eventSink ->
          eventSink?.let {
            Log.d("GTFlutter", "GTLibCoreFlutterPlugin sendMessageToFlutter - $messageJson")
            it.success(messageJson)
          } ?: kotlin.run {
            Log.d("GTFlutter", "GTLibCoreFlutterPlugin The eventSink is null.")
          }
        }
      }
    }
  }

  private var messageChannelFlutterApi:GTMessageChannelFlutterApi? = null
  private var methodChannel : MethodChannel? = null
  private var eventChannel : EventChannel? = null
  private var eventSink: EventChannel.EventSink? = null

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    Log.d("GTFlutter", "GTLibCoreFlutterPlugin onAttachedToEngine.")

    methodChannel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.gateio.flutter.lib_core.MethodChannel")
    methodChannel?.setMethodCallHandler(this)
    methodChannelList.add(methodChannel)

    eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, "com.gateio.flutter.lib_core.EventChannel")
    eventChannel?.setStreamHandler(this)

    // GTMessageChannelHostApi 设置实现类
    GTMessageChannelHostApi.setUp(flutterPluginBinding.binaryMessenger, GTFlutterMessageChannelImpl)
    // GTLoggerHostApi 设置实现类
    GTLoggerHostApi.setUp(flutterPluginBinding.binaryMessenger, GTLoggerHostApiImpl)

    // GTMessageChannelFlutterApi 设置实现类
    messageChannelFlutterApi = GTMessageChannelFlutterApi(flutterPluginBinding.binaryMessenger)
    messageChannelList.add(messageChannelFlutterApi!!)
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    when (call.method) {
      "notifyMultiEngineSync" -> {
        // 数据直接返回给 各Flutter 引擎
        methodChannelList.forEach { channel ->
          channel?.invokeMethod("listenMultiEngineSync", call.arguments)
        }
        result.success(true)
      }
      else -> result.notImplemented()
    }
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    Log.d("GTFlutter", "GTLibCoreFlutterPlugin onDetachedFromEngine.")

    methodChannelList.remove(methodChannel)
    methodChannel?.setMethodCallHandler(null)
    methodChannel = null

    eventSinkList.remove(eventSink)
    eventChannel?.setStreamHandler(null)
    eventChannel = null
    eventSink = null

    messageChannelList.remove(messageChannelFlutterApi)
    messageChannelFlutterApi = null
  }

  override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
    Log.d("GTFlutter", "GTLibCoreFlutterPlugin EventChannel onListen.")

    eventSink = events
    eventSinkList.add(eventSink)
    // 发送 粘性消息
    globalStickyMessageList.forEach {
      eventSink?.success(it)
    }
    globalStickyMessageList.clear()
  }

  override fun onCancel(arguments: Any?) {
    Log.d("GTFlutter", "GTLibCoreFlutterPlugin EventChannel onCancel.")

    eventSinkList.remove(eventSink)
    eventSink = null
  }

}
